package com.heima.search.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.heima.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.search.vos.SearchArticleVo;
import com.heima.search.service.ArticleSearchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {

    @Resource
    private ElasticsearchClient elasticsearchClient;
    private static final String INDEX_NAME = "app_info_article";


    /**
     * 实现es的分页搜索
     */
    @Override
    public ResponseResult<List<SearchArticleVo>> search(UserSearchDto userSearchDto) throws IOException {
        //1.构造query对象
        Query query = this.buildBasicQuery(userSearchDto);
        //分页参数
        int size = userSearchDto.getPageSize();
        int from = userSearchDto.getFromIndex();

        //2.进行搜索
        SearchResponse<SearchArticleVo> searchResponse = this.elasticsearchClient.search(builder -> builder
                        .index(INDEX_NAME)//要插入的索引库
                        .query(query)//查询条件
                        .size(size)//展示条数
                        .from(from)
                        .sort(s -> s.field(f -> f.field("publishTime").order(SortOrder.Desc)))//按照发布时间进行倒叙排序
                        .highlight(h -> h.fields("title", f -> f.
                                requireFieldMatch(false)
                                .preTags("<font style='color:red;font-size:inherit;'>")
                                .postTags("</font>")
                        ))//设置高亮
                , SearchArticleVo.class);

        //3.进行结果封装
        List<SearchArticleVo> searchArticleVos = CollStreamUtil.toList(searchResponse.hits().hits(), hit -> {
            SearchArticleVo source = hit.source();
            //进行数据处理
            //进行断言
            assert source != null;
            if (ObjectUtil.isNotEmpty(hit.highlight())) {
                String title = StrUtil.join("", hit.highlight().get("title"));
                source.setH_title(title);
            } else {
                source.setH_title(source.getTitle());
            }
            return source;
        });
        //返回数据
        return ResponseResult.okResult(searchArticleVos);
    }

    @Override
    public ResponseResult<List<String>> autoCompletion(UserSearchDto userSearchDto) {
        //1.使用百度的连接进行获得数据
        String url = StrUtil.format("https://www.baidu.com/sugrec?prod=pc&wd={}", userSearchDto.getSearchWords());
        HttpResponse response = HttpUtil.createGet(url).timeout(2000).execute();
        //获得返回的json格式数据
        JSONObject jsonObject = JSONUtil.parseObj(response.body());
        JSONArray gArray = jsonObject.getJSONArray("g");
        //将其中的数据全部拿到放到集合中
        List<String> qList = new ArrayList<>();
        for (int i = 0; i < gArray.size(); i++) {
            JSONObject suggestion = gArray.getJSONObject(i);
            String q = suggestion.get("q", String.class);
            qList.add(q);
        }

        return ResponseResult.okResult(qList);


    }

    /**
     * 构造query对象
     */
    private Query buildBasicQuery(UserSearchDto userSearchDto) {
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();
        if (StrUtil.isEmpty(userSearchDto.getSearchWords())) {
            //说明没查到数据,进行全部匹配查询
            boolQueryBuilder.must(builder -> builder.matchAll(m -> m));
        } else {
            //进行条件查询，关键字匹配
            boolQueryBuilder.must(builder -> builder.match(m -> m.field("all").query(userSearchDto.getSearchWords())));
        }
        return new Query.Builder()
                .bool(boolQueryBuilder.build()).build();
    }
}
